home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / SDKs / Word Services SDK 1.0.6 / Writeswell Jr 1.2.1 Sources ƒ / Writeswell Jr. Source / ObWind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-11  |  13.7 KB  |  579 lines  |  [TEXT/KAHL]

  1. /* ObWind.c
  2.  * Routines to handle cWindow objects
  3.  * ©1992 Working Software, Inc.
  4.  * This source code is copyrighted.  Permission is granted to use the Word Services
  5.  * portion of the Writeswell Jr. source code in your own programs, but you 
  6.  * may not distribute the Writeswell Jr. word-processor code as a 
  7.  * commercial product.  If you modify the code, please do not call it 
  8.  * Writeswell Jr. (or Writeswell.)  This will ensure that people understand the 
  9.  * program and don’t have to deal with a number of different versions with 
  10.  * who-knows-what going on in the code.
  11.  * 
  12.  * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
  13.  * 24 Dec 91 Mike Crawford
  14.  */
  15. #include <AppleEvents.h>
  16. #include <AEObjects.h>
  17. #include <AEPackObject.h>
  18. #include <AERegistry.h>
  19. #include "AppEvents.h"
  20. #include "ObWind.h"
  21. #include "ObText.h"
  22. #include "ObOSpec.h"
  23. #include "Gripe.h"
  24.  
  25. OSErr WindGetDataHandler( AEDesc *tokenPtr,
  26.                         AppleEvent *theAppleEventPtr,
  27.                         AppleEvent *replyEventPtr,
  28.                         long refCon );
  29. OSErr WindSetDataHandler( AEDesc *tokenPtr,
  30.                         AppleEvent *theAppleEventPtr,
  31.                         AppleEvent *replyEventPtr,
  32.                         long refCon );
  33. OSErr WindCountHandler( AEDesc *tokenPtr,
  34.                         AppleEvent *theAppleEventPtr,
  35.                         AppleEvent *replyEventPtr,
  36.                         long refCon );
  37.  
  38. /* Given the the direct object of an event is a window token (or property thereof),
  39.  * do the requested event.
  40.  */
  41. OSErr DispatchWind( AEDesc *tokenPtr,
  42.                         AppleEvent *theAppleEventPtr,
  43.                         AppleEvent *replyEventPtr,
  44.                         long refCon )
  45. {
  46.     OSErr            err;
  47.     AEEventClass    theClass;
  48.     AEEventID        theID;
  49.     
  50.     /* This function is only for the Core suit.  Get the event ID from the appleEvent
  51.      */
  52.     
  53.     err = GetEventID( theAppleEventPtr, &theID );
  54.     
  55.     switch ( theID ){
  56.         case kAEGetData:
  57.             err = WindGetDataHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
  58.             break;
  59.         case kAESetData:
  60.             err = WindSetDataHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
  61.             break;
  62.         case kAECountElements:
  63.             err = WindCountHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
  64.         default:
  65.             err = errAEEventNotHandled;
  66.             break;
  67.     }
  68.     
  69.     return noErr;
  70. }
  71.  
  72. /* The handlers for the various events */
  73.  
  74. /* Get Data */
  75.  
  76. OSErr WindGetDataHandler( AEDesc *tokenPtr,
  77.                         AppleEvent *theAppleEventPtr,
  78.                         AppleEvent *replyEventPtr,
  79.                         long refCon )
  80. {
  81.     WindowPtr        wp;
  82.     DescType        propCode;
  83.     WindTokenBody    **tokHdl;
  84.     AEDesc            replyValue;
  85.     Str255            tmpStr;
  86.     OSErr            err;
  87.  
  88.     /* Sanity check */
  89.     if ( tokenPtr->descriptorType != cWindow ){
  90.         Gripe( "\pGot wrong token type" );
  91.         return errAEEventNotHandled;
  92.     }
  93.  
  94.     tokHdl = (WindTokenBody**)(tokenPtr->dataHandle);
  95.     
  96.     wp = (*tokHdl)->theWindowPtr;
  97.     propCode = (*tokHdl)->propertyCode;
  98.     
  99.     if ( !wp ){
  100.         Gripe( "\pAttempting to get data for non-existent window" );
  101.         return errAENoSuchObject;
  102.     }
  103.  
  104.     switch ( propCode ){
  105.         case typeNull:
  106.             /* This is a magic number for "Not A Property".  I don't know if this
  107.              * is really kosher - gotta ask, but it is a convenience.
  108.              */
  109.             
  110.             /* Should return a string for object browsers */
  111.             Gripe( "\pTrying to GetData on a window object" );
  112.             return errAENoSuchObject;
  113.             break;
  114.         case pName:
  115.             GetWTitle( wp, tmpStr );
  116.                         
  117.             err = AECreateDesc( typeChar,
  118.                                 (Ptr)&(tmpStr[1]),
  119.                                 (Size)tmpStr[0],
  120.                                 &replyValue );
  121.             if ( err ){
  122.                 Gripe( "\pAECreateDesc failed" );
  123.                 return err;
  124.             }
  125.             break;
  126.         case pBounds:
  127.         case pClass:
  128.         case pHasTitleBar:
  129.         case pIndex:
  130.         case pIsModal:
  131.         case pIsResizable:
  132.         case pIsZoomed:
  133.         case pVisible:
  134.             Gripe( "\pGot a property type we do not yet implement" );
  135.             return errAENoSuchObject;
  136.             break;
  137.         default:
  138.             Gripe( "\pUnknown property type" );
  139.             return errAENoSuchObject;
  140.             break;
  141.     }
  142.     
  143.     /* At this point we have some kind of descriptor to stick in the reply */
  144.     
  145.     err = AEPutParamDesc( replyEventPtr,
  146.                             keyDirectObject,
  147.                             &replyValue );
  148.     if ( err ){
  149.         Gripe( "\pAEPutParamDesc failed" );
  150.         return err;
  151.     }
  152.     
  153.     err = AEDisposeDesc( &replyValue );
  154.     if ( err ){
  155.         Gripe( "\pAEDisposeDesc failed" );
  156.         return err;
  157.     }
  158.  
  159.     return noErr;
  160. }/* WindGetDataHandler */
  161.  
  162. /* Set Data */
  163.  
  164. OSErr WindSetDataHandler( AEDesc *tokenPtr,
  165.                         AppleEvent *theAppleEventPtr,
  166.                         AppleEvent *replyEventPtr,
  167.                         long refCon )
  168. {
  169.     WindowPtr        wp;
  170.     DescType        propCode;
  171.     WindTokenBody    **tokHdl;
  172.     AEDesc            newValue;
  173.     AEDesc            textValue;
  174.     OSErr            err;
  175.  
  176.     /* Sanity check */
  177.     if ( tokenPtr->descriptorType != cWindow ){
  178.         Gripe( "\pGot wrong token type" );
  179.         return errAEEventNotHandled;
  180.     }
  181.  
  182.     tokHdl = (WindTokenBody**)(tokenPtr->dataHandle);
  183.     
  184.     wp = (*tokHdl)->theWindowPtr;
  185.     propCode = (*tokHdl)->propertyCode;
  186.     
  187.     if ( !wp ){
  188.         Gripe( "\pAttempting to set data in non-existent window" );
  189.         return errAENoSuchObject;
  190.     }
  191.     
  192.     /* Get the value to set, whatever it is */
  193.     
  194.     err = AEGetParamDesc( theAppleEventPtr,
  195.                             keyAEData,
  196.                             typeWildCard,
  197.                             &newValue );
  198.     if ( err ){
  199.         Gripe( "\pAEGetParamDesc failed to get keyAEData" );
  200.         return err;
  201.     }                        
  202.  
  203.     switch ( propCode ){
  204.         case typeNull:
  205.             /* This is a magic number for "Not A Property".  I don't know if this
  206.              * is really kosher - gotta ask, but it is a convenience.
  207.              */
  208.             
  209.             /* I don't think it makes sense to Set Data on a window */
  210.             return errAEEventNotHandled;
  211.             break;
  212.         case pName:
  213.         
  214.             /* Make sure that the name is of type text */
  215.             err = AECoerceDesc( &newValue,
  216.                                 typePString,
  217.                                 &textValue );
  218.             if ( err ){
  219.                 Gripe( "\pAECoerceDesc failed to coerce to text" );
  220.                 return err;
  221.             }
  222.             
  223.             HLock( textValue.dataHandle );
  224.             
  225.             SetWTitle( wp, (ConstStr255Param) *(textValue.dataHandle) );
  226.                         
  227.             HUnlock( textValue.dataHandle );
  228.             
  229.             err = AEDisposeDesc( &textValue );
  230.             
  231.             if ( err ){
  232.                 Gripe( "\pAEDisposeDesc textValue failed" );
  233.                 return err;
  234.             }
  235.             
  236.             break;
  237.         case pBounds:
  238.         case pClass:
  239.         case pHasTitleBar:
  240.         case pIndex:
  241.         case pIsModal:
  242.         case pIsResizable:
  243.         case pIsZoomed:
  244.         case pVisible:
  245.             Gripe( "\pGot a property type we do not yet implement" );
  246.             return errAENoSuchObject;
  247.             break;
  248.         default:
  249.             Gripe( "\pUnknown property type" );
  250.             return errAENoSuchObject;
  251.             break;
  252.     }
  253.     
  254.     /* At this point we are done with the newValue descriptor */
  255.     
  256.     err = AEDisposeDesc( &newValue );
  257.     
  258.     if ( err ){
  259.         Gripe( "\pAEDisposeDesc newValue failed" );
  260.         return err;
  261.     }
  262.  
  263.     return noErr;
  264. }/* WindSetDataHandler */
  265.  
  266. /* Count Elements */
  267.  
  268. OSErr WindCountHandler( AEDesc *tokenPtr,
  269.                         AppleEvent *theAppleEventPtr,
  270.                         AppleEvent *replyEventPtr,
  271.                         long refCon )
  272. {
  273.     WindowPtr        wp;
  274.     DescType        propCode;
  275.     WindTokenBody    **tokHdl;
  276.     AEDesc            replyValue;
  277.     AEDesc            elementClassDesc;
  278.     DescType        elementClass;
  279.     long            count;
  280.     OSErr            err;
  281.  
  282.     /* Sanity check */
  283.     if ( tokenPtr->descriptorType != cWindow ){
  284.         Gripe( "\pGot wrong token type" );
  285.         return errAEEventNotHandled;
  286.     }
  287.  
  288.     tokHdl = (WindTokenBody**)(tokenPtr->dataHandle);
  289.     
  290.     wp = (*tokHdl)->theWindowPtr;
  291.     propCode = (*tokHdl)->propertyCode;
  292.     
  293.     if ( !wp ){
  294.         Gripe( "\pAttempting to count elements for non-existent window" );
  295.         return errAENoSuchObject;
  296.     }
  297.  
  298.     /* Get the class of element that we want to count.  We could reasonably
  299.      * count the letters of the title property, for example.  Presently we
  300.      * only support counting the object specifier elements for the word services
  301.      * table checking method.
  302.      */
  303.     
  304.     err = AEGetParamDesc( theAppleEventPtr,
  305.                             keyAEObjectClass,
  306.                             typeType,
  307.                             &elementClassDesc );
  308.     if ( err ){
  309.         Gripe( "\pCould not get object class from Count Elements event" );
  310.         return err;
  311.     }
  312.     
  313.     elementClass = *(DescType*)(*elementClassDesc.dataHandle);
  314.     
  315.     switch ( propCode ){
  316.         case typeNull:
  317.             /* This is a magic number for "Not A Property".  I don't know if this
  318.              * is really kosher - gotta ask, but it is a convenience.
  319.              */
  320.             
  321.             /* In this case, we are counting the actual elements of the window.  This
  322.              * can be a text field or an object specifier.  We check to see what
  323.              * kind of element is desired, and call a function for that class to count
  324.              * it.
  325.              *
  326.              * We do not yet handle the case where we could have multiple containers.
  327.              */
  328.  
  329.             switch ( elementClass ){
  330.                 case cText:
  331.                     err = CountTextInWind( wp, &count );
  332.                     if ( err )
  333.                         return err;
  334.                     break;
  335.                 case typeObjectSpecifier:
  336.                     err = CountOSpecInWind( wp, &count );
  337.                     if ( err )
  338.                         return err;
  339.                     break;
  340.                 default:
  341.                     return errAENoSuchObject;
  342.                     break;
  343.             }
  344.             
  345.             err = AECreateDesc( typeLongInteger, (Ptr)&count, sizeof( count ), &replyValue );
  346.             if ( err ){
  347.                 Gripe( "\pAECreateDesc failed" );
  348.                 return err;
  349.             }
  350.             break;
  351.         case pName:
  352.         case pBounds:
  353.         case pClass:
  354.         case pHasTitleBar:
  355.         case pIndex:
  356.         case pIsModal:
  357.         case pIsResizable:
  358.         case pIsZoomed:
  359.         case pVisible:
  360.             /* In all of these cases, we are counting the elements of a property.
  361.              * This makes more sense than it might seem.  It is reasonable to count
  362.              * the letters in the name, for example.
  363.              */
  364.             Gripe( "\pGot a property type we do not yet implement" );
  365.             return errAENoSuchObject;
  366.             break;
  367.         default:
  368.             Gripe( "\pUnknown property type" );
  369.             return errAENoSuchObject;
  370.             break;
  371.     }
  372.     
  373.     /* At this point we have some kind of descriptor to stick in the reply */
  374.  
  375.     err = AEPutParamDesc( replyEventPtr,
  376.                             keyDirectObject,
  377.                             &replyValue );
  378.     if ( err ){
  379.         Gripe( "\pAEPutParamDesc failed" );
  380.         return err;
  381.     }
  382.     
  383.     err = AEDisposeDesc( &replyValue );
  384.     if ( err ){
  385.         Gripe( "\pAEDisposeDesc failed" );
  386.         return err;
  387.     }
  388.  
  389.     return noErr;
  390. }
  391.  
  392. /* Return a Window token given a null (application) token */
  393.  
  394. pascal OSErr WindFromNull(DescType desiredClass,
  395.                             const AEDesc *container,
  396.                             DescType containerClass,
  397.                             DescType form,
  398.                             const AEDesc *selectionData,
  399.                             AEDesc *theToken,
  400.                             long LongInt)
  401. {
  402.     AEDesc            longKeyData;
  403.     WindowPtr        wp;
  404.     long            count;
  405.     WindTokenBody    tokData;
  406.     OSErr            err;
  407.  
  408.     /* Check that the container is what we intend.  This should only happen if we
  409.      * installed the token handler incorrectly.
  410.      */
  411.  
  412.     if ( container->descriptorType != typeNull )
  413.         return errAEEventNotHandled;
  414.     
  415.     /* find the window based on the key form */
  416.     
  417.     switch ( form ){
  418.         case formAbsolutePosition:
  419.             /* Make sure we really have a type long descriptor */
  420.             err = AECoerceDesc( selectionData, typeLongInteger, &longKeyData );
  421.             if ( err ){
  422.                 Gripe( "\pAECoerceDesc failed" );
  423.                 return err;
  424.             }
  425.             
  426.             count = **(long**)(longKeyData.dataHandle);
  427.             
  428.             /* We're done with the descriptor created in the coercion */
  429.             
  430.             err = AEDisposeDesc( &longKeyData );
  431.             if ( err ){
  432.                 Gripe( "\pAEDisposeDesc failed" );
  433.                 return err;
  434.             }
  435.             
  436.             /* In our particular case, we can have at most one window, but we write 
  437.              * this in a general way for reusability... scan the window list for the
  438.              * window
  439.              */
  440.              
  441.             wp = FrontWindow();
  442.             
  443.             while( count > 1 && wp != (WindowPtr)NULL ){
  444.                 wp = (WindowPtr)((WindowPeek)wp)->nextWindow;
  445.             }
  446.             
  447.             if ( wp == (WindowPtr)NULL ){
  448.                 Gripe( "\pNo window found" );
  449.                 return errAENoSuchObject;
  450.             }
  451.             
  452.             /* Actually create the token that we return */
  453.             tokData.theWindowPtr = wp;
  454.             tokData.propertyCode = typeNull;        /* This means it's not a property */
  455.             
  456.             err = AECreateDesc( desiredClass, (Ptr)&tokData, sizeof( tokData ), theToken );
  457.             if ( err ){
  458.                 Gripe( "\pAECreateDesc failed to create a token" );
  459.                 return err;
  460.             }
  461.             
  462.             return noErr;
  463.             break;
  464.         case formRelativePosition:
  465.         case formTest:
  466.         case formRange:
  467.         case formPropertyID:
  468.         case formName:
  469.             return errAEEventNotHandled;    /* Flesh this out later */
  470.             break;
  471.         default:
  472.             Gripe( "\pGot unexpected key form" );
  473.             return errAEEventNotHandled;
  474.     }
  475.         
  476.     return noErr;
  477. }
  478.  
  479. /* Return a property token given a cWindow token.  This works for any property of a window */
  480.  
  481. pascal OSErr PropFromWind(DescType desiredClass,
  482.                             const AEDesc *container,
  483.                             DescType containerClass,
  484.                             DescType form,
  485.                             const AEDesc *selectionData,
  486.                             AEDesc *theToken,
  487.                             long LongInt)
  488. {
  489.     OSErr        err;
  490.     DescType    propType;
  491.  
  492.     /* Check that the container is what we intend.  This should only happen if we
  493.      * installed the token handler incorrectly.
  494.      */
  495.  
  496.     if ( container->descriptorType != cWindow )
  497.         return errAEEventNotHandled;
  498.  
  499.     if ( form != formPropertyID ){
  500.         Gripe( "\pExpected formPropertyID" );
  501.         return errAEEventNotHandled;
  502.     }
  503.  
  504.     propType = **( (DescType**)(selectionData->dataHandle) );
  505.  
  506.     /* All we really do here is shove the property type into the token, if we
  507.      * know about the property type
  508.      */
  509.  
  510.     switch ( propType ){
  511.         case pName:
  512.             break;
  513.         case pBounds:
  514.         case pClass:
  515.         case pHasTitleBar:
  516.         case pIndex:
  517.         case pIsModal:
  518.         case pIsResizable:
  519.         case pIsZoomed:
  520.         case pVisible:
  521.             Gripe( "\pGot a property type we do not yet implement" );
  522.             return errAENoSuchObject;
  523.             break;
  524.         default:
  525.             Gripe( "\pUnknown property type" );
  526.             return errAENoSuchObject;
  527.             break;
  528.     }
  529.  
  530.     /* All we do in the token is put the propType into it.  We can start with the
  531.      * container descriptor as it has some of the fields filled in already.
  532.      */
  533.     
  534.     err = AEDuplicateDesc( container, theToken );
  535.     if ( err ){
  536.         Gripe( "\pAEDuplicateDesc failed" );
  537.         return err;
  538.     }
  539.     
  540.     (*(WindTokenBody**)(theToken->dataHandle))->propertyCode = propType;
  541.     
  542.     return noErr;
  543. }
  544.  
  545. /*
  546.  * Descriptor packing routines
  547.  */
  548.  
  549. /* Create a formAbsolutePosition window descriptor */
  550.  
  551. OSErr BuildWindowSpecifier( AEDesc *specPtr, long whichWindow )
  552. {
  553.     AEDesc    nullDesc;
  554.     AEDesc    nullSpec;
  555.     AEDesc    whichDesc;
  556.     OSErr    err;
  557.     
  558.     /* Create the descriptor for the container (the application, or null) */
  559.  
  560.     err = AECreateDesc( typeNull, (Ptr)NULL, (Size)0, &nullDesc );
  561.     if ( err )
  562.         return err;
  563.     
  564.     /* Create the key data, which gives the window number */
  565.     
  566.     err = CreateOffsetDescriptor( whichWindow, &whichDesc );
  567.     if ( err )
  568.         return err;
  569.  
  570.     /* Create the Object Specifier for the window */
  571.     
  572.     err = CreateObjSpecifier( cWindow,
  573.                                 &nullDesc,
  574.                                 formAbsolutePosition,
  575.                                 &whichDesc,
  576.                                 true,                    /* Dispose of input descriptors */
  577.                                 specPtr );                /* specPtr is the value we return */
  578.     return err;
  579. }